import { NextSeo } from 'next-seo';
import { Callout, Tabs } from 'nextra/components';

<NextSeo description="Access other AWS services from AWS Lambda by using the built-in AWS credentials." />

# AWS credentials on AWS Lambda

When your PHP application runs on AWS Lambda, it automatically has access to AWS credentials. This means you don't need to manage AWS access keys or credentials in your code - Lambda handles this for you.

<Callout type="warning">
    Don't deploy AWS access keys in your Lambda functions or environment variables. Lambda provides credentials automatically.

    This is a common mistake **when migrating an existing application to AWS Lambda**.
</Callout>

## How it works

Lambda functions **automatically get AWS access keys** in their environment variables. These credentials are temporary and managed by AWS, so you don't have to worry about rotating them or keeping them secure.

```php
echo $_SERVER['AWS_ACCESS_KEY_ID']; // AKIAIOSFODNN7EXAMPLE
echo $_SERVER['AWS_SECRET_ACCESS_KEY']; // wJalrXUtnFEM
echo $_SERVER['AWS_SESSION_TOKEN']; // AQoEXAMPLEH4aoAH0gNCAPy...
```

The PHP AWS SDK automatically detects and uses them. Here's an example with S3:

```php
$s3 = new \Aws\S3\S3Client([
    'version' => 'latest',
    'region' => $_SERVER['AWS_REGION'],
    // No credentials needed, the SDK uses the environment variables automatically
]);

// Use S3 normally
$result = $s3->putObject([
    'Bucket' => 'my-bucket',
    'Key' => 'file.txt',
    'Body' => 'Hello from Lambda!'
]);

// Note that this also works with https://async-aws.com
```

Note that **Laravel and Symfony automatically pick up these permissions** too.

These credentials have access controlled by an IAM role defined in `serverless.yml`.

<Callout type="info">
    By default, Lambda functions **don't have any access** (principle of least privilege). To access other AWS services (like S3 or SQS), you need to add permissions to that IAM role in `serverless.yml` (read below).
</Callout>

## Adding permissions

To grant your Lambda function access to AWS services, add IAM statements to your `serverless.yml`:

```yaml
service: my-app

provider:
    name: aws
    iam:
        role:
            statements:
                # IAM statements here...

functions:
    # ...
```

### Example: S3

To read and write files to an S3 bucket:

```yaml
provider:
    name: aws
    iam:
        role:
            statements:
                # Allow Lambda to read and write to S3
                -   Effect: Allow
                    Action:
                        - s3:GetObject
                        - s3:PutObject
                        - s3:DeleteObject
                    Resource: arn:aws:s3:::my-bucket/*
                # Allow listing bucket contents
                -   Effect: Allow
                    Action: s3:ListBucket
                    Resource: arn:aws:s3:::my-bucket
```

<Callout>
    If you use the [Lift `storage` construct](./storage.mdx#s3-storage) to create S3 buckets, it [automatically adds the necessary permissions](https://github.com/getlift/lift/blob/master/docs/storage.md#permissions) to your functions. No need to set up permissions manually!
</Callout>

### Example: SQS

To send and receive messages from SQS queues:

```yaml
provider:
    name: aws
    iam:
        role:
            statements:
                # Allow Lambda to access an SQS queue
                -   Effect: Allow
                    Action:
                        - sqs:SendMessage
                        - sqs:ReceiveMessage
                        - sqs:DeleteMessage
                        - sqs:GetQueueAttributes
                    Resource: arn:aws:sqs:${aws:region}:${aws:accountId}:my-queue
```

<Callout>
    If you use the [Lift `queue` construct](../use-cases/sqs.mdx#creating-sqs-queues) to create SQS queues, it [automatically adds the necessary permissions](https://github.com/getlift/lift/blob/master/docs/queue.md#permissions) to your functions. No need to set up permissions manually!
</Callout>

## Common services and permissions

Here are the IAM actions you'll typically need for common AWS services:

### DynamoDB
```yaml
-   Effect: Allow
    Action:
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
        - dynamodb:Query
        - dynamodb:Scan
    Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/my-table
```

### Secrets Manager
```yaml
-   Effect: Allow
    Action: secretsmanager:GetSecretValue
    Resource: arn:aws:secretsmanager:${aws:region}:${aws:accountId}:secret:my-secret-*
```

### SNS (notifications)
```yaml
-   Effect: Allow
    Action: sns:Publish
    Resource: arn:aws:sns:${aws:region}:${aws:accountId}:my-topic
```

### EventBridge
```yaml
-   Effect: Allow
    Action: events:PutEvents
    Resource: arn:aws:events:${aws:region}:${aws:accountId}:event-bus/my-event-bus
```

### SSM Parameter Store
```yaml
-   Effect: Allow
    Action:
        - ssm:GetParameter
        - ssm:GetParameters
    Resource: arn:aws:ssm:${aws:region}:${aws:accountId}:parameter/my-app/*
```

## Troubleshooting

### Access Denied errors

If you get "Access Denied" errors when trying to use AWS services:

1. Check that you've added the correct IAM permissions in `serverless.yml`
2. Verify the resource ARN is correct (bucket name, queue name, etc.)
3. Make sure you've redeployed after adding permissions
4. [Check the logs](./logs.mdx) for the exact error message

### Testing locally

When testing locally remember that you will need to provide AWS credentials since you're not running on Lambda. You can set them up via long-lived AWS access keys or IAM roles with SSO.

## Permissions per function

If you want to define permissions **per function**, instead of globally (ie: in the provider), you can install the plugin [`serverless-iam-roles-per-function`](https://github.com/functionalone/serverless-iam-roles-per-function) and then use the `iamRoleStatements` at the function definition block.

## Learn more

- [`serverless.yml` IAM guide](https://github.com/oss-serverless/serverless/blob/main/docs/guides/iam.md)
- [Documentation of the AWS SDK for PHP](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/)
